#include "fileio.h"
#include "windows/win32_fileio.h"
#include "ifile.h"

#include "core/cbuffer.h"

#include <cstring>
#include <atomic>

namespace renderit
{
	namespace fileio
	{
		ifile* open(const std::string& filename, int flag)
		{
			return win32_open(filename, flag);
		}
		
		bool exists(const std::string& filename)
		{
			return win32_exists(filename);
		}

		bool create_dir(const std::string& dirpath)
		{
			return win32_create_dir(dirpath);
		}

		bool ensure_dir(const std::string& dirpath)
		{
			core::cbuffer cb;
			cb.add(dirpath.data(), dirpath.length() + 1);

			char * q = cb.buf();
			char * p = q;
			while (*q) {
				char c = *q;
				if (c == '\\' || c == '/') {
					*q = 0;
					create_dir(p);
					*q = '\\';
				}
				q++;
			}

			return true;
		}

		bool is_directory(const std::string& filepath)
		{
			return win32_is_directory(filepath);
		}
		
		bool copy_file(const std::string& src, const std::string& dest)
		{
			ensure_dir(dest);
			return win32_copy_file(src, dest);
		}
		
		bool remove_file(const std::string& fpath)
		{
			return win32_remove_file(fpath);
		}
		
		std::vector<std::string> list_dir(const std::string& dirpath)
		{
			return win32_list_dir(dirpath.c_str());
		}

		std::string join(const std::string& dirpath, const std::string& fname)
		{
			if (!dirpath.size())
			{
				return fname;
			}
			std::string ret = dirpath;
			int len = dirpath.size();
			if ((ret[len - 1] != '/') && (ret[len - 1] != '\\'))
			{
				ret.push_back('/');
			}
			ret.append(fname);
			return ret;
		}

		std::string parent_dir(const std::string& path)
		{
			const char * data = path.data();
			int len = path.length();
			// ignore last '/': eg: C:/b/c/ --> C:/b
			int i;
			for (i = len - 2; i >= 0; --i) {
				if (data[i] == '/' || data[i] == '\\') {
					break;
				}
			}
			if (i > 0) {
				return path.substr(0, i);
			}
			return path;
		}
		
		long get_size(const std::string& path)
		{
			return win32_get_fsize(path);
		}
	}
}